package edu.uaskl.jqf.playground;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import edu.uaskl.jqf.algorithm.Deutsch;
import edu.uaskl.jqf.algorithm.QftModularExponentation;
import edu.uaskl.jqf.algorithm.util.Algorithms;
import edu.uaskl.jqf.model.Complex;
import edu.uaskl.jqf.model.Qubit;
import edu.uaskl.jqf.model.Quregister;
import edu.uaskl.jqf.model.gates.DeutschBlackBox;
import edu.uaskl.jqf.model.gates.Hadamard;
import edu.uaskl.jqf.model.gates.util.Gates;
import edu.uaskl.jqf.model.matrix.MatrixComplex;
import edu.uaskl.jqf.model.matrix.MatrixTransformationHessenberg;
import edu.uaskl.jqf.tools.Sorting;
import edu.uaskl.jqf.tools.StopWatch;
import edu.uaskl.jqf.tools.matrix.MatrixTransformations;
import edu.uaskl.jqf.tools.matrix.MatrixSolvers;

public class _tbach {
  public static void main(final String[] args) {
    System.out.println(Qubit.q1.tensor(Qubit.q1));
    System.out.println(Qubit.q1.tensor(Qubit.q1).tensor(Qubit.q0));
    System.out.println(Qubit.q1.tensor(Qubit.q1).tensor(Qubit.q0).tensor(Qubit.q1));
    System.out.println(Qubit.q1.tensor(Qubit.q0).tensor(Qubit.q0));
    System.out.println(new MatrixComplex(new double[][] { { 1 }, { 2 } }).tensor(new MatrixComplex(new double[][] { { 3 }, { 4 } })));
    System.out.println(new MatrixComplex(new double[][] { { 1 }, { 2 }, { 3 } }).tensor(new MatrixComplex(new double[][] { { -1 } })));
    System.out.println(new MatrixComplex(new double[][] { { 1, 2 }, { 3, 4 } }).tensor(new MatrixComplex(new double[][] { { -4, -3 }, { -2, -1 } })));
    System.out.println(new MatrixComplex(new Complex[][] { { new Complex(2, 3) }, { new Complex(3, -2) } }).getAdjoint().multiply(
        new MatrixComplex(new Complex[][] { { new Complex(4, 0) }, { new Complex(5, 1) } })));
    System.out.println(new MatrixComplex(new Complex[][] { { new Complex(4, 0) }, { new Complex(5, 1) } }).getAdjoint().multiply(
        new MatrixComplex(new Complex[][] { { new Complex(2, 3) }, { new Complex(3, -2) } })));
    System.out.println(new Qubit(3.0 / 5, 4.0 / 5));
    final double sqrt20Inv = 1.0 / Math.sqrt(20);
    System.out.println(new Qubit(new Complex(0, 4 * sqrt20Inv), new Complex(-2 * sqrt20Inv)));
    final double sqrt18Inv = 1.0 / (3 * Math.sqrt(2));
    System.out.println(new Qubit(new Complex(2, -2).multiply(sqrt18Inv), new Complex(1, 3).multiply(sqrt18Inv)));

    // testEntropySubsystems();
    // demonstration3();
    // demonstration5HomeisterBase7();
    // demonstration6ChuangNielsonBase7Iqft();
    // demonstration4Paper();
    // final Quregister quregisterLarge = new Quregister(8).applyAlgorithm(Algorithms.randomCoin);
    // final MatrixComplex matrixComplexQft = Gates.QFT.getSize(256);
    // final MatrixComplex matrixComplexIdentity = Gates.IDENTITY.getSize(1);
    // final MatrixComplex matrixComplexQftTensor = matrixComplexQft.tensor(matrixComplexIdentity).getAdjoint();
    // System.out.println(matrixComplexQft);
    // System.out.println(matrixComplexQft.getAdjoint());
    // System.out.println(matrixComplexIdentity);
    // System.out.println(matrixComplexQftTensor);
    // System.out.println(matrixComplexQft.multiply(quregisterLarge.getQubitRegister()));
  }

  static void testEntropySubsystems() {
    final Quregister quregisterLarge = new Quregister(2).applyAlgorithm(Algorithms.randomCoin);
    final Quregister quregisterSmall = new Quregister(0, 0);
    final MatrixComplex densityLarge = quregisterLarge.getQubitRegister().multiply(quregisterLarge.getQubitRegister().getAdjoint());
    final MatrixComplex densitySmall = quregisterSmall.getQubitRegister().multiply(quregisterSmall.getQubitRegister().getAdjoint());
    System.out.println(densityLarge);
    System.out.println(densitySmall);
    System.out.println(densityLarge.getEntropy());
    System.out.println(densitySmall.getEntropy());
  }

  static void demonstration6ChuangNielsonBase7Iqft() { // Page 235
    final StopWatch stopWatch = new StopWatch("shor chuang nielson");

    final int base = 7;
    final int modulus = 15;
    final int numberOfQftBits = 7;
    final int numberOfModBits = 4;

    final Quregister quregisterLarge = new Quregister(numberOfQftBits).applyAlgorithm(Algorithms.randomCoin);
    final Quregister quregisterSmall = new Quregister(0, 0, 0, 0);

    final List<Qubit> qubitsAll = new ArrayList<>();
    qubitsAll.addAll(quregisterLarge.getQubits());
    qubitsAll.addAll(quregisterSmall.getQubits());
    System.out.println("qubitsAll: " + qubitsAll);

    final Quregister quRegister = new Quregister(qubitsAll);
    System.out.println("quRegister: " + quRegister);
    System.out.println("quRegister as Vector: " + quRegister.getQubitRegister());
    final int qftSize = 1 << numberOfQftBits;
    final int modexpSize = 1 << numberOfModBits;

    final Quregister quregister = new QftModularExponentation(base, modulus, numberOfQftBits, numberOfModBits).apply(quRegister);
    stopWatch.tick("QftModularExponentation done");

    final MatrixComplex resultMatrixExp = quregister.getQubitRegister();
    System.out.println(resultMatrixExp);

    final MatrixComplex matrixComplexIqft = Gates.IQFT.getSize(qftSize);
    final MatrixComplex matrixComplexIdentity = Gates.IDENTITY.getSize(modexpSize);
    final MatrixComplex matrixComplexIqftTensor = matrixComplexIqft.tensor(matrixComplexIdentity);
    stopWatch.tick("qft matrix created done");

    final MatrixComplex resultMatrixAll = matrixComplexIqftTensor.multiply(resultMatrixExp);
    stopWatch.tick("matrix multiplication done");
    System.out.println(resultMatrixAll);

    final Map<Integer, Integer> mapResultToCount = measureMatrixAndGetMap(resultMatrixAll);
    stopWatch.tick("measurement done");

    showFinalMeasurementQFT(mapResultToCount, numberOfQftBits);
    stopWatch.stop();
    /*
    final int base = 7;
    final int modulus = 15;
    final int numberOfQftBits = 7;
    final int numberOfModBits = 4;
    measurement done, took: 1191ms
    {4=31742, 1=31509, 7=31476, 1540=31379, 1031=31305, 1549=31268, 513=31257, 1025=31208, 1028=31201, 1543=31199, 13=31185, 1537=31159, 519=31116, 525=31081, 516=30995, 1037=30920}
    Number: 1, count: 31509, binary: 1, shiftedBinary: 0, shifted: 0
    Number: 4, count: 31742, binary: 100, shiftedBinary: 0, shifted: 0
    Number: 7, count: 31476, binary: 111, shiftedBinary: 0, shifted: 0
    Number: 13, count: 31185, binary: 1101, shiftedBinary: 0, shifted: 0
    Number: 513, count: 31257, binary: 1000000001, shiftedBinary: 100, shifted: 4
    Number: 516, count: 30995, binary: 1000000100, shiftedBinary: 100, shifted: 4
    Number: 519, count: 31116, binary: 1000000111, shiftedBinary: 100, shifted: 4
    Number: 525, count: 31081, binary: 1000001101, shiftedBinary: 100, shifted: 4
    Number: 1025, count: 31208, binary: 10000000001, shiftedBinary: 1000, shifted: 8
    Number: 1028, count: 31201, binary: 10000000100, shiftedBinary: 1000, shifted: 8
    Number: 1031, count: 31305, binary: 10000000111, shiftedBinary: 1000, shifted: 8
    Number: 1037, count: 30920, binary: 10000001101, shiftedBinary: 1000, shifted: 8
    Number: 1537, count: 31159, binary: 11000000001, shiftedBinary: 1100, shifted: 12
    Number: 1540, count: 31379, binary: 11000000100, shiftedBinary: 1100, shifted: 12
    Number: 1543, count: 31199, binary: 11000000111, shiftedBinary: 1100, shifted: 12
    Number: 1549, count: 31268, binary: 11000001101, shiftedBinary: 1100, shifted: 12
    runs: 500000, map size: 16
     */
  }

  static void demonstration5HomeisterBase7() {
    final StopWatch stopWatch = new StopWatch("shor homeister");

    final int base = 13; // 2^4 = 1 + 1*15 # 7^4 = 1 + 160*15 # 11^2 = 1 + 8*15 # 13^4 = 1 + 28.560*15
    final int modulus = 15;
    final int numberOfQftBits = 4;
    final int numberOfModBits = 4;

    final Quregister quregisterLarge = new Quregister(numberOfQftBits).applyAlgorithm(Algorithms.randomCoin);
    final Quregister quregisterSmall = new Quregister(0, 0, 0, 0);

    final List<Qubit> qubitsAll = new ArrayList<>();
    qubitsAll.addAll(quregisterLarge.getQubits());
    qubitsAll.addAll(quregisterSmall.getQubits());
    System.out.println("qubitsAll: " + qubitsAll);

    final Quregister quRegister = new Quregister(qubitsAll);
    System.out.println("quRegister: " + quRegister);
    // System.out.println("quRegister as Vector: " + quRegister.getQubitRegister());
    final int qftSize = 1 << numberOfQftBits;
    final int modexpSize = 1 << numberOfModBits;

    final Quregister quregister = new QftModularExponentation(base, modulus, numberOfQftBits, numberOfModBits).apply(quRegister);
    stopWatch.tick("QftModularExponentation done");

    final MatrixComplex resultMatrixExp = quregister.getQubitRegister();

    final Map<Integer, Integer> mapResultToCountExp = measureMatrixAndGetMap(resultMatrixExp);
    for (final Entry<Integer, Integer> mapEntrySet : Sorting.sortByKeyIncreasing(mapResultToCountExp).entrySet()) {
      final int key = mapEntrySet.getKey();
      final int value = mapEntrySet.getValue();
      System.out.printf("Number: %4d, count: %d, prop: %3.2f,  binary: %8s, leftPart: %2d, rightPart: %2d\n", key, value, (100.0 * value) / MEASURE_RUNS,
          Integer.toBinaryString(key), key >> numberOfQftBits, key & ((1 << numberOfQftBits) - 1));
    }
    // System.out.println(resultMatrixExp);

    final MatrixComplex matrixComplexQft = Gates.QFT.getSize(qftSize);
    final MatrixComplex matrixComplexIdentity = Gates.IDENTITY.getSize(modexpSize);
    final MatrixComplex matrixComplexQftTensor = matrixComplexQft.tensor(matrixComplexIdentity);
    stopWatch.tick("qft matrix created done");

    final MatrixComplex resultMatrixAll = matrixComplexQftTensor.multiply(resultMatrixExp);
    stopWatch.tick("matrix multiplication done");
    // System.out.println(resultMatrixAll);

    final Map<Integer, Integer> mapResultToCount = measureMatrixAndGetMap(resultMatrixAll);
    stopWatch.tick("measurement done");

    showFinalMeasurementQFT(mapResultToCount, numberOfQftBits);

    stopWatch.stop();

    /*
    final int base = 7;
    final int modulus = 15;
    final int numberOfQftBits = 4;
    final int numberOfModBits = 4;
    measurement done, took: 553ms
    {1=31607, 205=31584, 135=31349, 199=31335, 7=31318, 132=31315, 196=31312, 129=31296, 68=31286, 77=31242, 13=31180, 71=31145, 141=31092, 193=31019, 65=30999, 4=30921}
    Number:   1, count: 31607, binary:        1, shiftedBinary:    0, shifted:  0
    Number:   4, count: 30921, binary:      100, shiftedBinary:    0, shifted:  0
    Number:   7, count: 31318, binary:      111, shiftedBinary:    0, shifted:  0
    Number:  13, count: 31180, binary:     1101, shiftedBinary:    0, shifted:  0
    Number:  65, count: 30999, binary:  1000001, shiftedBinary:  100, shifted:  4
    Number:  68, count: 31286, binary:  1000100, shiftedBinary:  100, shifted:  4
    Number:  71, count: 31145, binary:  1000111, shiftedBinary:  100, shifted:  4
    Number:  77, count: 31242, binary:  1001101, shiftedBinary:  100, shifted:  4
    Number: 129, count: 31296, binary: 10000001, shiftedBinary: 1000, shifted:  8
    Number: 132, count: 31315, binary: 10000100, shiftedBinary: 1000, shifted:  8
    Number: 135, count: 31349, binary: 10000111, shiftedBinary: 1000, shifted:  8
    Number: 141, count: 31092, binary: 10001101, shiftedBinary: 1000, shifted:  8
    Number: 193, count: 31019, binary: 11000001, shiftedBinary: 1100, shifted: 12
    Number: 196, count: 31312, binary: 11000100, shiftedBinary: 1100, shifted: 12
    Number: 199, count: 31335, binary: 11000111, shiftedBinary: 1100, shifted: 12
    Number: 205, count: 31584, binary: 11001101, shiftedBinary: 1100, shifted: 12
    runs: 500000, map size: 16
     */
  }

  static final int MEASURE_RUNS = 500_000;

  /** Measure {@value #MEASURE_RUNS} times the given matrix. Returns a map with value and counts. */
  static Map<Integer, Integer> measureMatrixAndGetMap(final MatrixComplex matrixComplex) {
    final Quregister quRegisterFinal = new Quregister(matrixComplex);
    final Map<Integer, Integer> mapResultToCount = new HashMap<>();
    for (int i = 0; i < MEASURE_RUNS; i++) {
      final int result = quRegisterFinal.measureAsDecimal();
      increaseMapCountFor(mapResultToCount, result);
    }
    return mapResultToCount;
  }

  public static void increaseMapCountFor(final Map<Integer, Integer> mapResultToCount, final Integer number) {
    final Integer mapResult = mapResultToCount.get(number);
    final Integer newValue = mapResult == null ? 1 : mapResult + 1;
    mapResultToCount.put(number, newValue);
  }

  public static void showFinalMeasurementQFT(final Map<Integer, Integer> mapResultToCount, final int numberOfQftBits) {
    System.out.println("\nfinal measurements:");
    System.out.println(Sorting.sortByValueDecreasing(mapResultToCount));
    for (final Entry<Integer, Integer> mapEntrySet : Sorting.sortByKeyIncreasing(mapResultToCount).entrySet()) {
      final int key = mapEntrySet.getKey();
      final int value = mapEntrySet.getValue();
      System.out.printf("Number: %4d, count: %d, prop: %3.2f,  binary: %8s, leftPart: %2d, rightPart: %2d\n", key, value, (100.0 * value) / MEASURE_RUNS,
          Integer.toBinaryString(key), key >> numberOfQftBits, key & ((1 << numberOfQftBits) - 1));
    }
    System.out.printf("runs: %d, map size: %d\n", MEASURE_RUNS, mapResultToCount.size());
  }

  // base 11
  static void demonstration4Paper() {
    final StopWatch stopWatch = new StopWatch("shor paper");

    final int base = 11;
    final int modulus = 15;
    final int numberOfQftBits = 9;
    final int numberOfModBits = 4;

    System.out.println("start");
    final Quregister quregisterLarge = new Quregister(numberOfQftBits).applyAlgorithm(Algorithms.randomCoin);
    final Quregister quregisterSmall = new Quregister(0, 0, 0, 1);

    final List<Qubit> qubitsAll = new ArrayList<>();
    qubitsAll.addAll(quregisterLarge.getQubits());
    qubitsAll.addAll(quregisterSmall.getQubits());
    System.out.println(qubitsAll);

    final Quregister quRegister = new Quregister(qubitsAll);
    final int qftSize = 1 << numberOfQftBits;
    final int modexpSize = 1 << numberOfModBits;

    final Quregister quregister = new QftModularExponentation(base, modulus, numberOfQftBits, numberOfModBits).apply(quRegister);
    stopWatch.tick("QftModularExponentation done");

    final MatrixComplex resultMatrixExp = quregister.getQubitRegister();
    System.out.println(resultMatrixExp);

    final MatrixComplex matrixComplexIqft = Gates.IQFT.getSize(qftSize);
    final MatrixComplex matrixComplexIdentity = Gates.IDENTITY.getSize(modexpSize);
    final MatrixComplex matrixComplexIqftTensor = matrixComplexIqft.tensor(matrixComplexIdentity);
    stopWatch.tick("qft matrix created done");

    final MatrixComplex resultMatrixAll = matrixComplexIqftTensor.multiply(resultMatrixExp);
    stopWatch.tick("matrix multiplication done");
    System.out.println(resultMatrixAll);

    final Map<Integer, Integer> mapResultToCount = measureMatrixAndGetMap(resultMatrixAll);
    stopWatch.tick("measurement done");

    showFinalMeasurementQFT(mapResultToCount, numberOfQftBits);
    stopWatch.stop();
    /*
     *
    final int base = 11;
    final int modulus = 15;
    final int numberOfQftBits = 9;
    final int numberOfModBits = 4;
    final measurements:
    {4107=125193, 11=125079, 1=124987, 4097=124741}
    Number: 1, count: 124987, binary: 1, shiftedBinary: 0, shifted: 0
    Number: 11, count: 125079, binary: 1011, shiftedBinary: 0, shifted: 0
    Number: 4097, count: 124741, binary: 1000000000001, shiftedBinary: 1000, shifted: 8
    Number: 4107, count: 125193, binary: 1000000001011, shiftedBinary: 1000, shifted: 8
    runs: 500000, map size: 4
     */
  }

  // calculate eigenvalues and entanglement for all bases
  static void demonstration3() {
    final long timestart = System.currentTimeMillis();
    System.out.println("start");
    final Quregister quregisterLarge = new Quregister(8).applyAlgorithm(Algorithms.randomCoin);
    final Quregister quregisterSmall = new Quregister(0, 0, 0, 1);

    final List<Qubit> qubitsAll = new ArrayList<>();
    qubitsAll.addAll(quregisterLarge.getQubits());
    qubitsAll.addAll(quregisterSmall.getQubits());
    System.out.println(qubitsAll);
    System.out.println();

    final Quregister quRegister = new Quregister(qubitsAll);
    int base = 13;
    final int modulus = 15;
    final int numberOfQftBits = 8;
    final int numberOfModBits = 4;

    for (int i = 2; i < 15; i++) {
      base = i;
      final Quregister quregister = new QftModularExponentation(base, modulus, numberOfQftBits, numberOfModBits).apply(quRegister);
      final long time1 = System.currentTimeMillis();
      System.out.println("QftModularExponentation done, took: " + (time1 - timestart) + "ms");

      final MatrixComplex resultMatrix = quregister.getQubitRegister();
      // System.out.println(resultMatrix);
      // System.exit(0);
      final MatrixComplex densityMatrix = resultMatrix.multiply(resultMatrix.getAdjoint());

      final long time2 = System.currentTimeMillis();
      System.out.println("density matrix created done, took: " + (time2 - time1) + "ms, overall: " + (time2 - timestart) + "ms\n");

      final MatrixComplex A = densityMatrix.getPartialTraceFirst(1 << numberOfQftBits);
      printQuantumEntropy(A, "A");
      System.out.println();
      final MatrixComplex B = densityMatrix.getPartialTraceSecond(1 << numberOfModBits);
      final long end = printQuantumEntropy(B, "B");
      System.out.println("done with: " + base + ", took: " + (end - time1) + "ms\n");
      System.out.println("#########################################################################\n");
    }
  }

  /*
  start
  [+ 0.707106781186548 * |0> + 0.707106781186548 * |1>, + 0.707106781186548 * |0> + 0.707106781186548 * |1>, + 0.707106781186548 * |0> + 0.707106781186548 * |1>, + 0.707106781186548 * |0> + 0.707106781186548 * |1>, + 0.707106781186548 * |0> + 0.707106781186548 * |1>, + 0.707106781186548 * |0> + 0.707106781186548 * |1>, + 0.707106781186548 * |0> + 0.707106781186548 * |1>, + 0.707106781186548 * |0> + 0.707106781186548 * |1>, + 1 * |0> + 0 * |1>, + 1 * |0> + 0 * |1>, + 1 * |0> + 0 * |1>, + 0 * |0> + 1 * |1>]
  base: 2, modulus: 15dimension: 4096x1
  QftModularExponentation done, took: 61ms
  density matrix created done, took: 4701ms, overall: 4762ms

  eigenValuesA (256): [+ 0, + 0.25, + 0, + 0.25, + 0.003843245967742, + 0, + 0.246156754032258, + 0, + 0.25, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0]
  entanglementA: + 1.406154017277613, tr(A): + 1, eigenValuesSum: + 1

  eigenValuesB (16): [+ 0, + 0.25, + 0.25, + 0, + 0.25, + 0, + 0, + 0, + 0.25, + 0, + 0, + 0, + 0, + 0, + 0, + 0]
  entanglementB: + 1.38629436111989, tr(B): + 1, eigenValuesSum: + 1
  done with: 2, took: 5273ms

  base: 3, modulus: 15dimension: 4096x1
  QftModularExponentation done, took: 5343ms
  density matrix created done, took: 10398ms, overall: 15741ms

  eigenValuesA (256): [+ 0.00390625, + 0, + 0.25, + 0, + 0.25, + 0.003843245967742, + 0, + 0.246156754032258, + 0, + 0.24609375, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0]
  entanglementA: + 1.426275226544615, tr(A): + 1, eigenValuesSum: + 1

  eigenValuesB (16): [+ 0, + 0.00390625, + 0, + 0.25, + 0, + 0, + 0.24609375, + 0, + 0, + 0.25, + 0, + 0, + 0.25, + 0, + 0, + 0]
  entanglementB: + 1.406415570386892, tr(B): + 1, eigenValuesSum: + 1
  done with: 3, took: 14371ms

  base: 4, modulus: 15dimension: 4096x1
  QftModularExponentation done, took: 19723ms
  density matrix created done, took: 3645ms, overall: 23368ms

  eigenValuesA (256): [+ 0, + 0.5, + 0.003875248015873, + 0, + 0.496124751984127, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0]
  entanglementA: + 0.7158410713666, tr(A): + 1, eigenValuesSum: + 1

  eigenValuesB (16): [+ 0, + 0.5, + 0, + 0, + 0.5, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0]
  entanglementB: + 0.693147180559945, tr(B): + 1, eigenValuesSum: + 1
  done with: 4, took: 4025ms

  base: 5, modulus: 15dimension: 4096x1
  QftModularExponentation done, took: 23748ms
  density matrix created done, took: 4159ms, overall: 27907ms

  eigenValuesA (256): [+ 0.00390625, + 0, + 0.5, + 0.003875, + 0, + 0.49221875, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0]
  entanglementA: + 0.738653551305766, tr(A): + 1, eigenValuesSum: + 1

  eigenValuesB (16): [+ 0, + 0.00390625, + 0, + 0, + 0, + 0.5, + 0, + 0, + 0, + 0, + 0.49609375, + 0, + 0, + 0, + 0, + 0]
  entanglementB: + 0.715991375096937, tr(B): + 1, eigenValuesSum: + 1
  done with: 5, took: 4347ms

  base: 6, modulus: 15dimension: 4096x1
  QftModularExponentation done, took: 28096ms
  density matrix created done, took: 622ms, overall: 28718ms

  eigenValuesA (256): [+ 0.00390625, + 0.011322367919284, + 0.012127778692242, + 0.012764955089683, + 0.013308411717938, + 0.013795802891202, + 0.012872944294649 - 2.1452296784E-5i, + 0.015758638305317, + 0.01377037846557, + 0.014473272379879, + 0.014220037890993, + 0.014272266681379 - 1.369212917E-5i, + 0.016213897747359, + 0.014970928483413, + 0.014688764549035, + 0.014734587242881, + 0.015408215056585, + 0.015544485672137, + 0.015204693055167, + 0.015164941548958, + 0.015654958008341, + 0.016193596668072 + 1.9145811744E-5i, + 0.015514503266414, + 0.015242802462574, + 0.014882089948194, + 0.014461997438692, + 0.013972829311007, + 0.012756449583154, + 0.013407749337582, + 0.016119369348896, + 0.015477657619286, + 0.015304787516854, + 0.015080386742431, + 0.014809660001243, + 0.014482188556465, + 0.014071236292049, + 0.013943326018949, + 0.013542050274017, + 0.013224530649674, + 0.012925225352684, + 0.012643612216562, + 0.012379044773058, + 0.012135604565377, + 0.011908840606518, + 0.011694412792818, + 0.011488106097741, + 0.011282214126148, + 0.011082725917224, + 0.010885887569705, + 0.010690495641443, + 0.010498950869017, + 0.010309667405019, + 0.010122365920072, + 0.009936311403235, + 0.009750824818051, + 0.00956397586521, + 0.009378459146498, + 0.009189790517979, + 0.00900154680714, + 0.008812495314516, + 0.008622864353166, + 0.008432484222721, + 0.008242210983885, + 0.008051119348432, + 0.007860248878022, + 0.007669247613129, + 0.007478308916406, + 0.007287529074126, + 0.007097669836979, + 0.006907031980464, + 0.00671783630789, + 0.006529061033021, + 0.006341151863911, + 0.006153911861834, + 0.005967813968219, + 0.005782803254857, + 0.005598967809997, + 0.005416477389935, + 0.005235415142699, + 0.005055893668007, + 0.004878020430652, + 0.004701889623102, + 0.004527633597295, + 0.004355335541798, + 0.004185103019585, + 0.004017038753968, + 0.003851244251247, + 0.003687812606987, + 0.003526852985884, + 6.52310145576E-4 + 0.001108784739518i, + 0.00103266836446 + 0.001157692308654i, + 0.001408917945567 + 0.00112003934144i, + 0.001752617955655 + 0.001010248249939i, + 0.002044672467337 + 8.57515710407E-4i, + 0.003368400110756, + 0.002288823634315 + 6.91860240199E-4i, + 0.002500864853968 + 5.31397485533E-4i, + 0.00269885169651 + 3.70606995377E-4i, + 0.003214167844132, + 0.00287504248222 + 2.07066272265E-4i, + 0.003038261247847 + 4.8991071933E-5i, + 0.003038261166223 - 4.8991160376E-5i, + 0.002875042477474 - 2.07066098024E-4i, + 2.98786513109E-4 + 9.66178169905E-4i, + 1.2303846961E-5 + 7.3115901688E-4i, + 0.002698851429772 - 3.70607886245E-4i, + 0.002500862660803 - 5.31396477799E-4i, + 0.002288825572143 - 6.91860554516E-4i, + 0.002044672634339 - 8.5751593274E-4i, + 0.001752618096578 - 0.001010248171293i, - 1.58067830825E-4 + 4.21498277277E-4i, + 0.001408917953057 - 0.001120039377039i, + 0.001032667370571 - 0.001157691761684i, + 6.52310240285E-4 - 0.001108786636459i, + 2.98786209619E-4 - 9.66177729705E-4i, + 1.2303225784E-5 - 7.31153502797E-4i, - 1.58063086034E-4 - 4.21503340785E-4i, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0]
  entanglementA: + 4.55104558404039, tr(A): + 1, eigenValuesSum: + 1

  eigenValuesB (16): [+ 0, + 0.00390625, + 0, + 0, + 0, + 0, + 0.99609375, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0]
  entanglementB: + 0.025559460044412, tr(B): + 1, eigenValuesSum: + 1
  done with: 6, took: 5834ms

  base: 7, modulus: 15dimension: 4096x1
  QftModularExponentation done, took: 33931ms
  density matrix created done, took: 531ms, overall: 34462ms

  eigenValuesA (256): [+ 0, + 0.25, + 0, + 0.25, + 0.003843245967742, + 0, + 0.246156754032258, + 0, + 0.25, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0]
  entanglementA: + 1.406154017277613, tr(A): + 1, eigenValuesSum: + 1

  eigenValuesB (16): [+ 0, + 0.25, + 0, + 0, + 0.25, + 0, + 0, + 0.25, + 0, + 0, + 0, + 0, + 0, + 0.25, + 0, + 0]
  entanglementB: + 1.38629436111989, tr(B): + 1, eigenValuesSum: + 1
  done with: 7, took: 4719ms

  base: 8, modulus: 15dimension: 4096x1
  QftModularExponentation done, took: 38651ms
  density matrix created done, took: 732ms, overall: 39383ms

  eigenValuesA (256): [+ 0, + 0.25, + 0, + 0.25, + 0.003843245967742, + 0, + 0.246156754032258, + 0, + 0.25, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0]
  entanglementA: + 1.406154017277613, tr(A): + 1, eigenValuesSum: + 1

  eigenValuesB (16): [+ 0, + 0.25, + 0.25, + 0, + 0.25, + 0, + 0, + 0, + 0.25, + 0, + 0, + 0, + 0, + 0, + 0, + 0]
  entanglementB: + 1.38629436111989, tr(B): + 1, eigenValuesSum: + 1
  done with: 8, took: 5471ms

  base: 9, modulus: 15dimension: 4096x1
  QftModularExponentation done, took: 44123ms
  density matrix created done, took: 823ms, overall: 44946ms

  eigenValuesA (256): [+ 0.00390625, + 0, + 0.5, + 0.003875, + 0, + 0.49221875, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0]
  entanglementA: + 0.738653551305766, tr(A): + 1, eigenValuesSum: + 1

  eigenValuesB (16): [+ 0, + 0.00390625, + 0, + 0, + 0, + 0, + 0.49609375, + 0, + 0, + 0.5, + 0, + 0, + 0, + 0, + 0, + 0]
  entanglementB: + 0.715991375096937, tr(B): + 1, eigenValuesSum: + 1
  done with: 9, took: 6663ms

  base: 10, modulus: 15dimension: 4096x1
  QftModularExponentation done, took: 50786ms
  density matrix created done, took: 719ms, overall: 51505ms

  eigenValuesA (256): [+ 0.00390625, + 0.011322367919284, + 0.012127778692242, + 0.012764955089683, + 0.013308411717938, + 0.013795802891202, + 0.012872944294649 - 2.1452296784E-5i, + 0.015758638305317, + 0.01377037846557, + 0.014473272379879, + 0.014220037890993, + 0.014272266681379 - 1.369212917E-5i, + 0.016213897747359, + 0.014970928483413, + 0.014688764549035, + 0.014734587242881, + 0.015408215056585, + 0.015544485672137, + 0.015204693055167, + 0.015164941548958, + 0.015654958008341, + 0.016193596668072 + 1.9145811744E-5i, + 0.015514503266414, + 0.015242802462574, + 0.014882089948194, + 0.014461997438692, + 0.013972829311007, + 0.012756449583154, + 0.013407749337582, + 0.016119369348896, + 0.015477657619286, + 0.015304787516854, + 0.015080386742431, + 0.014809660001243, + 0.014482188556465, + 0.014071236292049, + 0.013943326018949, + 0.013542050274017, + 0.013224530649674, + 0.012925225352684, + 0.012643612216562, + 0.012379044773058, + 0.012135604565377, + 0.011908840606518, + 0.011694412792818, + 0.011488106097741, + 0.011282214126148, + 0.011082725917224, + 0.010885887569705, + 0.010690495641443, + 0.010498950869017, + 0.010309667405019, + 0.010122365920072, + 0.009936311403235, + 0.009750824818051, + 0.00956397586521, + 0.009378459146498, + 0.009189790517979, + 0.00900154680714, + 0.008812495314516, + 0.008622864353166, + 0.008432484222721, + 0.008242210983885, + 0.008051119348432, + 0.007860248878022, + 0.007669247613129, + 0.007478308916406, + 0.007287529074126, + 0.007097669836979, + 0.006907031980464, + 0.00671783630789, + 0.006529061033021, + 0.006341151863911, + 0.006153911861834, + 0.005967813968219, + 0.005782803254857, + 0.005598967809997, + 0.005416477389935, + 0.005235415142699, + 0.005055893668007, + 0.004878020430652, + 0.004701889623102, + 0.004527633597295, + 0.004355335541798, + 0.004185103019585, + 0.004017038753968, + 0.003851244251247, + 0.003687812606987, + 0.003526852985884, + 6.52310145576E-4 + 0.001108784739518i, + 0.00103266836446 + 0.001157692308654i, + 0.001408917945567 + 0.00112003934144i, + 0.001752617955655 + 0.001010248249939i, + 0.002044672467337 + 8.57515710407E-4i, + 0.003368400110756, + 0.002288823634315 + 6.91860240199E-4i, + 0.002500864853968 + 5.31397485533E-4i, + 0.00269885169651 + 3.70606995377E-4i, + 0.003214167844132, + 0.00287504248222 + 2.07066272265E-4i, + 0.003038261247847 + 4.8991071933E-5i, + 0.003038261166223 - 4.8991160376E-5i, + 0.002875042477474 - 2.07066098024E-4i, + 2.98786513109E-4 + 9.66178169905E-4i, + 1.2303846961E-5 + 7.3115901688E-4i, + 0.002698851429772 - 3.70607886245E-4i, + 0.002500862660803 - 5.31396477799E-4i, + 0.002288825572143 - 6.91860554516E-4i, + 0.002044672634339 - 8.5751593274E-4i, + 0.001752618096578 - 0.001010248171293i, - 1.58067830825E-4 + 4.21498277277E-4i, + 0.001408917953057 - 0.001120039377039i, + 0.001032667370571 - 0.001157691761684i, + 6.52310240285E-4 - 0.001108786636459i, + 2.98786209619E-4 - 9.66177729705E-4i, + 1.2303225784E-5 - 7.31153502797E-4i, - 1.58063086034E-4 - 4.21503340785E-4i, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0]
  entanglementA: + 4.55104558404039, tr(A): + 1, eigenValuesSum: + 1

  eigenValuesB (16): [+ 0, + 0.00390625, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.99609375, + 0, + 0, + 0, + 0, + 0]
  entanglementB: + 0.025559460044412, tr(B): + 1, eigenValuesSum: + 1
  done with: 10, took: 6032ms

  base: 11, modulus: 15dimension: 4096x1
  QftModularExponentation done, took: 56819ms
  density matrix created done, took: 574ms, overall: 57393ms

  eigenValuesA (256): [+ 0, + 0.5, + 0.003875248015873, + 0, + 0.496124751984127, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0]
  entanglementA: + 0.7158410713666, tr(A): + 1, eigenValuesSum: + 1

  eigenValuesB (16): [+ 0, + 0.5, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.5, + 0, + 0, + 0, + 0]
  entanglementB: + 0.693147180559945, tr(B): + 1, eigenValuesSum: + 1
  done with: 11, took: 6471ms

  base: 12, modulus: 15dimension: 4096x1
  QftModularExponentation done, took: 63291ms
  density matrix created done, took: 855ms, overall: 64146ms

  eigenValuesA (256): [+ 0.00390625, + 0, + 0.25, + 0, + 0.25, + 0.003843245967742, + 0, + 0.246156754032258, + 0, + 0.24609375, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0]
  entanglementA: + 1.426275226544615, tr(A): + 1, eigenValuesSum: + 1

  eigenValuesB (16): [+ 0, + 0.00390625, + 0, + 0.25, + 0, + 0, + 0.24609375, + 0, + 0, + 0.25, + 0, + 0, + 0.25, + 0, + 0, + 0]
  entanglementB: + 1.406415570386892, tr(B): + 1, eigenValuesSum: + 1
  done with: 12, took: 5884ms

  base: 13, modulus: 15dimension: 4096x1
  QftModularExponentation done, took: 69176ms
  density matrix created done, took: 530ms, overall: 69706ms

  eigenValuesA (256): [+ 0, + 0.25, + 0, + 0.25, + 0.003843245967742, + 0, + 0.246156754032258, + 0, + 0.25, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0]
  entanglementA: + 1.406154017277613, tr(A): + 1, eigenValuesSum: + 1

  eigenValuesB (16): [+ 0, + 0.25, + 0, + 0, + 0.25, + 0, + 0, + 0.25, + 0, + 0, + 0, + 0, + 0, + 0.25, + 0, + 0]
  entanglementB: + 1.38629436111989, tr(B): + 1, eigenValuesSum: + 1
  done with: 13, took: 6699ms

  base: 14, modulus: 15dimension: 4096x1
  QftModularExponentation done, took: 75876ms
  density matrix created done, took: 721ms, overall: 76597ms

  eigenValuesA (256): [+ 0, + 0.5, + 0.003875248015873, + 0, + 0.496124751984127, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0]
  entanglementA: + 0.7158410713666, tr(A): + 1, eigenValuesSum: + 1

  eigenValuesB (16): [+ 0, + 0.5, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.5, + 0]
  entanglementB: + 0.693147180559945, tr(B): + 1, eigenValuesSum: + 1
  done with: 14, took: 5611ms


   */

  static long printQuantumEntropy(final MatrixComplex matrixComplex, final String identificator) {
    final StopWatch stopWatch = new StopWatch("printQuantumEntropy " + identificator);
    final List<Complex> eigenValues = matrixComplex.getEigenValues();
    stopWatch.tick("got eigenvalues");
    System.out.println("eigenValues " + identificator + " (" + eigenValues.size() + "): " + eigenValues);
    Complex entropy = Complex.get00();
    Complex eigenValuesSum = Complex.get00();
    // sum over all eigenvalues -y: y*ln(y)
    for (final Complex complex : eigenValues) {
      if (complex.equals(Complex.get00())) {
        continue;
      }
      // System.out.printf("complex: %s, ln: %s, mul: %s\n", complex, complex.getLn(), complex.multiply(complex.getLn()));
      eigenValuesSum = eigenValuesSum.add(complex);
      entropy = entropy.add(complex.multiply(complex.getLog2()));
    }
    System.out.println("entanglement/entropy " + identificator + ": " + entropy.multiply(new Complex(-1)) + ", tr(" + identificator + "): "
        + matrixComplex.getTrace() + ", eigenValuesSum: " + eigenValuesSum);
    return stopWatch.stop();
  }

  static void writeMatrixComplex(final MatrixComplex matrix) {
    try {
      Files.write(Paths.get("C:\\tmp\\densitymatrix.txt"), Arrays.asList(matrix.toString()), StandardCharsets.UTF_8);
    }
    catch (final IOException exception) {
      exception.printStackTrace();
    }
  }

  static void demonstration2() {
    System.out.println(Qubit.q0.tensor(Qubit.q0));
    System.out.println(Qubit.q0.tensor(Qubit.q1));
    System.out.println(Qubit.q1.tensor(Qubit.q0));
    System.out.println(Qubit.q1.tensor(Qubit.q1));

    System.out.println(Gates.HADAMARD.multiply(Qubit.q0));
    System.out.println(Gates.HADAMARD.multiply(Qubit.q1));
    // System.out.println(Gates.HADAMARD.multiply(Qubit.q0).tensor(Gates.HADAMARD.multiply(Qubit.q1)));
    //
    // System.out.println(new Quregister(1, 1, 1));
    // System.out.println(new Quregister(1, 1, 1).getQubitRegister());
    //
    // System.out.println(new Complex(0, Math.PI).getExp());
    // System.out.println(Complex.getNthRootsOfUnity(4));
    // System.out.println();
    // System.out.println(Gates.QFT.getSize(4));
    // System.out.println(Gates.QFT.getSize(4).getAdjoint());

    System.out.println("---");
    System.out.println(Gates.HADAMARD.multiply(Qubit.q0.tensor(Qubit.q1)));

    final Complex[] A40 = { new Complex(1.0, 4.0), new Complex(2.0, 4.0), new Complex(3.0, 4.0), new Complex(4.0, 4.0) };
    final Complex[] A41 = { new Complex(2.0, 4.0), new Complex(2.0, 3.0), new Complex(3.0, 3.0), new Complex(4.0, 3.0) };
    final Complex[] A42 = { new Complex(3.0, 4.0), new Complex(3.0, 3.0), new Complex(3.0, 2.0), new Complex(4.0, 2.0) };
    final Complex[] A43 = { new Complex(4.0, 4.0), new Complex(4.0, 3.0), new Complex(4.0, 2.0), new Complex(4.0, 1.0) };
    final Complex[][] A4 = { A40, A41, A42, A43 };
    final MatrixComplex MA4 = MatrixComplex.createMatrixBasedOnArray2d(A4);
    System.out.println(MA4);

    final MatrixTransformationHessenberg matrixTransformationHessenberg = MatrixTransformations.HESSENBERG.transform(MA4);
    System.out.println(matrixTransformationHessenberg);

    System.out.println(MatrixSolvers.EIGEN.solve(matrixTransformationHessenberg));

    System.out.println(Qubit.q1.tensor(Qubit.q1).tensor(Qubit.q0).tensor(Qubit.q1));
  }

  static void demonstration() {
    System.out.println(Hadamard.size2.multiply(Qubit.q1));
    System.out.println(Gates.HADAMARD.multiply(Qubit.q0));
    System.out.println(Gates.HADAMARD.tensor(Hadamard.size2));
    System.out.println("hadamard 4:");
    System.out.println(Gates.HADAMARD.tensor(Hadamard.size4));
    System.out.println(Hadamard.size2.tensor(Hadamard.size2));
    System.out.println(Hadamard.size2.tensor(Hadamard.size4));

    System.out.println("Random:");
    Quregister qRegister = new Quregister(10);
    qRegister = qRegister.applyAlgorithm(Algorithms.randomCoin);
    System.out.println(qRegister.measure() + " = " + qRegister.measureAsDecimal());

    System.out.println("Deutsch constant:");
    qRegister = new Quregister(0, 1);
    qRegister = qRegister.applyAlgorithm(new Deutsch(DeutschBlackBox.exampleConstant));
    System.out.println(qRegister);
    System.out.println(qRegister.measure() + " = " + qRegister.measureAsDecimal());
    System.out.println("Deutsch balanced:");
    qRegister = new Quregister(0, 1);
    qRegister = qRegister.applyAlgorithm(new Deutsch(DeutschBlackBox.exampleBalanced));
    System.out.println(qRegister);
    System.out.println(qRegister.measure() + " = " + qRegister.measureAsDecimal());

    // System.out.println(DeutschBlackBox.exampleBalanced.multiply(Hadamard.size4.multiply(Qubit.q0.tensor(Qubit.q1))));
    System.out.println();
    System.out.println(Gates.HADAMARD.multiply(Gates.CNOT.getInstance()));
  }

  static void demonstrationPartialTraceEigenvalues() {
    final MatrixComplex h0 = new MatrixComplex(Gates.HADAMARD.multiply(Qubit.q0).getValuesCopy());
    final MatrixComplex ht = h0.tensor(h0);
    System.out.println(ht);
    final MatrixComplex m1 = ht.multiply(ht.getAdjoint());
    System.out.println(m1);
    final MatrixComplex c = m1.getPartialTraceFirst(2);
    System.out.println("\nc:");
    System.out.println(c);
    System.out.println(Gates.HADAMARD.getSize(2));
    System.out.println(c.getEigenValues());
    System.out.println(Gates.HADAMARD.getSize(2).getEigenValues());

    System.out.println("\nh0.multiply(h0.getAdjoint())");
    System.out.println(h0.multiply(h0.getAdjoint()));
  }
}
